/**
* @program: Go
*
* @description:
*
* @author: Mr.chen
*
* @create: 2020-08-14 14:21
**/
package globle

import (
	"bytes"
	"errors"
	"fmt"
	"github.com/nfnt/resize"
	"image"
	"image/gif"
	"image/jpeg"
	"image/png"
	"io"
	"os"
	"os/exec"
	"regexp"
	"strings"
)
const (
	LOCAL_FILE_DIR    = "mnt"
	MIN_FILE_SIZE     = 1       // bytes
	MAX_FILE_SIZE     = 10000000 // bytes
	MAX_WIDTH_HEIGHT  = 1280
	IMAGE_TYPES       = "(jpg|gif|p?jpeg|(x-)?png)"
)
var (
	typemap = map[int]string{1:"bigpic",2:"smallpic",3:"bigsmallpic",4:"media/mp4",5:"media/mp3"}
	acceptFileTypes = regexp.MustCompile(IMAGE_TYPES)
)
type FileInfo struct {
	Url          string `json:"url,omitempty"`
	Name         string `json:"name"`
	Type         string `json:"type"`
	Size         int64  `json:"size"`
	Error        string `json:"error,omitempty"`
}

func (fi *FileInfo) ValidateType() (valid bool) {
	if acceptFileTypes.MatchString(fi.Type) {
		return true
	}
	fi.Error = "Filetype not allowed"
	return false
}
func (fi *FileInfo) ValidateSize() (valid bool) {
	if fi.Size < MIN_FILE_SIZE {
		fi.Error = "File is too small"
	} else if fi.Size > MAX_FILE_SIZE {
		fi.Error = "File is too big"
	} else {
		return true
	}
	return false
}

/*
* 图片裁剪
* 入参:1、file，2、输出路径，3、原图width，4、原图height，5、精度
* 规则:照片生成缩略图尺寸为190*135，先进行缩小，再进行平均裁剪
*
* 返回:error
 */
func createSmallPic_clip(in io.Reader, fileSmall string, w, h, quality int) error {
	x0 := 0
	x1 := 190
	y0 := 0
	y1 := 135
	sh := h*190/w
	sw := w*135/h
	origin, fm, err := image.Decode(in)
	if err != nil {
		return err
	}
	if sh > 135 {
		origin = resize.Resize(uint(190), uint(sh), origin, resize.Lanczos3)
		y0 = (sh - 135) / 4
		y1 = y0 + 135
	} else {
		origin = resize.Resize(uint(sw), uint(135), origin, resize.Lanczos3)
		x0 = (sw - 190) / 2
		x1 = x0 + 190
	}
	out, err := os.Create(fileSmall)
	if err != nil {
		return err
	}
	switch fm {
	case "jpeg":
		img := origin.(*image.YCbCr)
		subImg := img.SubImage(image.Rect(x0, y0, x1, y1)).(*image.YCbCr)
		return jpeg.Encode(out, subImg, &jpeg.Options{quality})
	case "png":
		switch origin.(type) {
		case *image.NRGBA:
			img := origin.(*image.NRGBA)
			subImg := img.SubImage(image.Rect(x0, y0, x1, y1)).(*image.NRGBA)
			return png.Encode(out, subImg)
		case *image.RGBA:
			img := origin.(*image.RGBA)
			subImg := img.SubImage(image.Rect(x0, y0, x1, y1)).(*image.RGBA)
			return png.Encode(out, subImg)
		}
	case "gif":
		img := origin.(*image.Paletted)
		subImg := img.SubImage(image.Rect(x0, y0, x1, y1)).(*image.Paletted)
		return gif.Encode(out, subImg, &gif.Options{})
	default:
		return errors.New("ERROR FORMAT")
	}
	return nil
}

/*
* 缩略图生成
* 入参:1、file，2、输出路径，3、输出width，4、输出height，5、精度
* 规则: width,height是想要生成的尺寸
*
* 返回:error
 */
func createSmallPic_scale(in io.Reader, fileSmall string, width, height, quality int) error {
	origin, fm, err := image.Decode(in)
	if err != nil {
		return err
	}
	if width == 0 || height == 0 {
		width = origin.Bounds().Max.X
		height = origin.Bounds().Max.Y
		//限制保存原图的长宽最大允许像素
		maxnum := MAX_WIDTH_HEIGHT
		if width < height && height > maxnum {
			width = width*maxnum/height
			height = maxnum
		} else if width >= height && width > maxnum {
			height = height*maxnum/width
			width = maxnum
		}
	}
	if quality == 0 {
		quality = 100
	}
	canvas := resize.Resize(uint(width), uint(height), origin, resize.Lanczos3)
	out, err := os.Create(fileSmall)
	if err != nil {
		return err
	}
	switch fm {
	case "jpeg":
		return jpeg.Encode(out, canvas, &jpeg.Options{quality})
	case "png":
		return png.Encode(out, canvas)
	case "gif":
		return gif.Encode(out, canvas, &gif.Options{})
	default:
		return errors.New("ERROR FORMAT")
	}
	return nil
}

func ChangetoSmall(src string) string {
	arr1 := strings.Split(src, "/")
	filename := arr1[len(arr1)-1]
	arr2 := strings.Split(filename, ".")
	ext := "." + arr2[len(arr2)-1]
	small := strings.Replace(src, ext, "_small"+ext, 1)
	return small
}

func RetMaxWH(w, h, max int) (int,int) {
	var sw, sh int
	if w < h && h > max {
		sh = max
		sw = w * max/h
	} else if w >= h && w > max {
		sw = max
		sh = h * max/w
	} else {
		sw = w
		sh = h
	}
	return sw, sh
}

func RetRealWHEXT(in io.Reader) (int, int, string, error) {
	origin, fm, err := image.Decode(in)
	if err != nil {
		return 0, 0, "", err
	}
	w := origin.Bounds().Max.X
	h := origin.Bounds().Max.Y
	return w, h, fm, err
}

func GetFrame(filename string, mediajpgPath string) *bytes.Buffer {
	cmd := exec.Command("ffmpeg", "-i", filename, "-y", "-f", "image2", "-t", "0.001", mediajpgPath)
	buf := new(bytes.Buffer)
	cmd.Stdout = buf
	if err := cmd.Run(); err != nil {
		fmt.Println(err)
	}
	return buf
}
